package com.kmxd.ams.app.archive;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kmxd.ams.client.archive.IArchiveFieldSvc;
import com.kmxd.ams.client.archive.IArchiveOrderFieldSvc;
import com.kmxd.ams.client.archive.IArchiveOssSettingSvc;
import com.kmxd.ams.client.archive.dto.ArchiveFieldQueryDTO;
import com.kmxd.ams.client.archive.dto.ArchiveOssSettingAddDTO;
import com.kmxd.ams.client.archive.dto.ArchiveOssSettingEditDTO;
import com.kmxd.ams.client.archive.dto.ArchiveOssSettingQueryDTO;
import com.kmxd.ams.client.archive.vo.ArchiveFieldListVO;
import com.kmxd.ams.client.archive.vo.ArchiveOssSettingListVO;
import com.kmxd.ams.client.archive.vo.ArchiveOssSettingVO;
import com.kmxd.ams.core.common.constant.ArchConst;
import com.kmxd.ams.core.common.enums.OssSettingEnum;
import com.kmxd.ams.core.util.IdUtil;
import com.kmxd.ams.core.util.SecurityUtil;
import com.kmxd.ams.infra.archive.entity.ArchiveField;
import com.kmxd.ams.infra.archive.entity.ArchiveOssSetting;
import com.kmxd.ams.infra.archive.mapper.ArchiveFieldMapper;
import com.kmxd.ams.infra.archive.mapper.ArchiveOssSettingMapper;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 存储路径设置 服务实现类
 *
 * @author nickbi
 * @since 2022-07-23
 */
@Service
@AllArgsConstructor
public class ArchiveOssSettingSvcImpl
    extends ServiceImpl<ArchiveOssSettingMapper, ArchiveOssSetting>
    implements IArchiveOssSettingSvc {

  private ArchiveOssSettingMapper archiveOssSettingMapper;
  private IArchiveOrderFieldSvc archiveOrderFieldSvc;
  private IArchiveFieldSvc archiveFieldSvc;
  private ArchiveFieldMapper archiveFieldMapper;

  @Override
  public Page<ArchiveOssSettingListVO> selectPage(Page reqPage, ArchiveOssSettingQueryDTO req) {
    LambdaQueryWrapper<ArchiveOssSetting> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.eq(
        Objects.nonNull(req.getFondsId()), ArchiveOssSetting::getFondsId, req.getFondsId());
    queryWrapper.eq(
        Objects.nonNull(req.getArchTypeId()),
        ArchiveOssSetting::getArchTypeId,
        req.getArchTypeId());
    queryWrapper.eq(Objects.nonNull(req.getType()), ArchiveOssSetting::getType, req.getType());
    queryWrapper.eq(
        Objects.nonNull(req.getFieldKey()), ArchiveOssSetting::getFieldKey, req.getFieldKey());
    queryWrapper.like(
        StrUtil.isNotBlank(req.getFieldName()),
        ArchiveOssSetting::getFieldName,
        req.getFieldName());

    queryWrapper.orderByAsc(ArchiveOssSetting::getType, ArchiveOssSetting::getSort);
    Page<ArchiveOssSetting> page = archiveOssSettingMapper.selectPage(reqPage, queryWrapper);
    Page<ArchiveOssSettingListVO> voPage = BeanUtil.copyProperties(page, Page.class);
    voPage.setRecords(BeanUtil.copyToList(page.getRecords(), ArchiveOssSettingListVO.class));
    return voPage;
  }

  @Override
  public List<ArchiveOssSettingListVO> selectList(ArchiveOssSettingQueryDTO req) {
    LambdaQueryWrapper<ArchiveOssSetting> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.eq(
        Objects.nonNull(req.getFondsId()), ArchiveOssSetting::getFondsId, req.getFondsId());
    queryWrapper.eq(
        Objects.nonNull(req.getArchTypeId()),
        ArchiveOssSetting::getArchTypeId,
        req.getArchTypeId());
    queryWrapper.eq(Objects.nonNull(req.getType()), ArchiveOssSetting::getType, req.getType());
    queryWrapper.eq(
        Objects.nonNull(req.getFieldKey()), ArchiveOssSetting::getFieldKey, req.getFieldKey());
    queryWrapper.like(
        StrUtil.isNotBlank(req.getFieldName()),
        ArchiveOssSetting::getFieldName,
        req.getFieldName());
    queryWrapper.eq(Objects.nonNull(req.getSort()), ArchiveOssSetting::getSort, req.getSort());
    queryWrapper.orderByAsc(ArchiveOssSetting::getType, ArchiveOssSetting::getSort);
    List<ArchiveOssSetting> list = archiveOssSettingMapper.selectList(queryWrapper);
    return BeanUtil.copyToList(list, ArchiveOssSettingListVO.class);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void add(ArchiveOssSettingAddDTO req) {
    req.setFondsId(
        ObjectUtil.isNotEmpty(req.getFondsId()) ? req.getFondsId() : SecurityUtil.getFondsId());
    ArchiveOssSetting entity = BeanUtil.copyProperties(req, ArchiveOssSetting.class);
    archiveOssSettingMapper.insert(entity);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void edit(ArchiveOssSettingEditDTO req) {
    ArchiveOssSetting entity = BeanUtil.copyProperties(req, ArchiveOssSetting.class);
    archiveOssSettingMapper.updateById(entity);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void remove(String ids) {
    Set<Long> idList = IdUtil.split(ids);
    this.baseMapper.deleteBatchIds(idList);
  }

  @Override
  public ArchiveOssSettingVO view(Long id) {
    ArchiveOssSetting entity = archiveOssSettingMapper.selectById(id);
    return BeanUtil.copyProperties(entity, ArchiveOssSettingVO.class);
  }

  @Override
  public List<ArchiveFieldListVO> getPath(ArchiveOssSettingQueryDTO req) {
    List<ArchiveOssSettingListVO> list =
        selectList(req).stream()
            .filter(item -> NumberUtil.equals(item.getType(), OssSettingEnum.PATH.getCode()))
            .collect(Collectors.toList());
    List<String> fields =
        list.stream().map(ArchiveOssSettingListVO::getFieldKey).collect(Collectors.toList());
    ArchiveFieldQueryDTO qry = new ArchiveFieldQueryDTO();
    qry.setTableId(req.getTableId());
    qry.setArchTypeId(req.getArchTypeId());
    qry.setDbFieldKeyList(fields);
    if (fields.isEmpty()) {
      return Lists.newArrayList();
    }
    LambdaQueryWrapper<ArchiveField> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.eq(ArchiveField::getTableId, req.getTableId());
    queryWrapper.eq(ArchiveField::getArchTypeId, req.getArchTypeId());
    queryWrapper.in(ArchiveField::getDbFieldKey, fields);

    List<ArchiveField> lists = archiveFieldMapper.selectList(queryWrapper);
    // 判断是否包含特殊名称，门类中文名，全宗名称
    List<ArchiveOssSettingListVO> fieldOther =
        list.stream()
            .filter(
                x ->
                    ObjectUtil.equals(x.getFieldKey(), ArchConst.OSS_SETTING_ARCH_TYPE_KEY)
                        || ObjectUtil.equals(x.getFieldKey(), ArchConst.OSS_SETTING_FONDS_KEY))
            .collect(Collectors.toList());
    if (!fieldOther.isEmpty()) {
      fieldOther.forEach(
          item -> {
            ArchiveField field = BeanUtil.copyProperties(item, ArchiveField.class);
            field.setDbFieldKey(item.getFieldKey());
            field.setDbFieldName(item.getFieldName());
            lists.add(field);
          });
    }

    List<ArchiveField> listsSort =
        lists.stream()
            .map(
                item -> {
                  ArchiveOssSettingListVO ossSettingListVO =
                      list.stream()
                          .filter(x -> ObjectUtil.equals(x.getFieldKey(), item.getDbFieldKey()))
                          .findFirst()
                          .orElse(null);

                  item.setSort(
                      ObjectUtil.isNotEmpty(ossSettingListVO)
                          ? ossSettingListVO.getSort()
                          : item.getSort());

                  return item;
                })
            .sorted(Comparator.comparing(ArchiveField::getSort))
            .collect(Collectors.toList());
    return BeanUtil.copyToList(listsSort, ArchiveFieldListVO.class);
  }

  @Override
  public List<ArchiveFieldListVO> getName(ArchiveOssSettingQueryDTO req) {
    List<ArchiveOssSettingListVO> list =
        selectList(req).stream()
            .filter(item -> NumberUtil.equals(item.getType(), OssSettingEnum.NAME.getCode()))
            .collect(Collectors.toList());
    List<String> fields =
        list.stream().map(ArchiveOssSettingListVO::getFieldKey).collect(Collectors.toList());
    ArchiveFieldQueryDTO qry = new ArchiveFieldQueryDTO();
    qry.setTableId(req.getTableId());
    qry.setArchTypeId(req.getArchTypeId());
    qry.setDbFieldKeyList(fields);
    if (fields.isEmpty()) {
      return Lists.newArrayList();
    }
    LambdaQueryWrapper<ArchiveField> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.eq(ArchiveField::getTableId, req.getTableId());
    queryWrapper.eq(ArchiveField::getArchTypeId, req.getArchTypeId());
    queryWrapper.in(ArchiveField::getDbFieldKey, fields);
    List<ArchiveField> lists = archiveFieldMapper.selectList(queryWrapper);
    // 判断是否包含特殊名称，门类中文名，全宗名称
    List<ArchiveOssSettingListVO> fieldOther =
        list.stream()
            .filter(
                x ->
                    ObjectUtil.equals(x.getFieldKey(), ArchConst.OSS_SETTING_ARCH_TYPE_KEY)
                        || ObjectUtil.equals(x.getFieldKey(), ArchConst.OSS_SETTING_FONDS_KEY))
            .collect(Collectors.toList());
    if (!fieldOther.isEmpty()) {
      fieldOther.forEach(
          item -> {
            ArchiveField field = BeanUtil.copyProperties(item, ArchiveField.class);
            field.setDbFieldKey(item.getFieldKey());
            field.setDbFieldName(item.getFieldName());
            lists.add(field);
          });
    }
    List<ArchiveField> listsSort =
        lists.stream()
            .map(
                item -> {
                  ArchiveOssSettingListVO ossSettingListVO =
                      list.stream()
                          .filter(x -> ObjectUtil.equals(x.getFieldKey(), item.getDbFieldKey()))
                          .findFirst()
                          .orElse(null);

                  item.setSort(
                      ObjectUtil.isNotEmpty(ossSettingListVO)
                          ? ossSettingListVO.getSort()
                          : item.getSort());

                  return item;
                })
            .sorted(Comparator.comparing(ArchiveField::getSort))
            .collect(Collectors.toList());

    return BeanUtil.copyToList(listsSort, ArchiveFieldListVO.class);
  }
}
